/*
 * Copyright 2021 Roberto Leinardi.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.leinardi.ohos.speeddial;

import ohos.agp.colors.RgbColor;
import ohos.agp.components.*;
import ohos.agp.components.element.Element;
import ohos.agp.components.element.ShapeElement;
import ohos.agp.utils.Color;
import ohos.agp.utils.LayoutAlignment;
import ohos.agp.utils.TextTool;
import ohos.app.Context;

/**
 * View that contains fab button and its label.
 */
public class FabWithLabelView extends DirectionalLayout {
    private static final String TAG = FabWithLabelView.class.getSimpleName();

    private Text mLabelTextView;
    private FloatingActionButton mFab;
    private CardView mLabelCardView;
    private boolean mIsLabelEnabled;
    private SpeedDialActionItem mSpeedDialActionItem;
    private SpeedDialView.OnActionSelectedListener mOnActionSelectedListener;
    private int mCurrentFabSize;
    private float mLabelCardViewElevation;
    private Element mLabelCardViewBackground;

    public FabWithLabelView(Context context) {
        super(context);
        init(context, null);
    }

    public FabWithLabelView(Context context, AttrSet attrs) {
        super(context, attrs);
        init(context, attrs);
    }

    public FabWithLabelView(Context context, AttrSet attrs, String styleName) {
        super(context, attrs, styleName);
        init(context, attrs);
    }

    /**
     * Init custom attributes.
     *
     * @param context context.
     * @param attrs   attributes.
     */
    private void init(Context context, AttrSet attrs) {
        Component rootView = LayoutScatter.getInstance(context).parse(ResourceTable.Layout_sd_fab_with_label_view, this, true);
        rootView.setFocusable(FOCUS_DISABLE);
        rootView.setTouchFocusable(false);

        mFab = (FloatingActionButton)rootView.findComponentById(ResourceTable.Id_sd_fab);
        mLabelTextView = (Text) rootView.findComponentById(ResourceTable.Id_sd_label);
        mLabelCardView = (CardView) rootView.findComponentById(ResourceTable.Id_sd_label_container);

        mLabelTextView.setMaxTextWidth(AttrHelper.fp2px(192, context));
        mLabelTextView.setTruncationMode(Text.TruncationMode.ELLIPSIS_AT_END);

        setFabSize(FloatingActionButton.SIZE_MINI);
        setOrientation(DirectionalLayout.HORIZONTAL);
        setClipEnabled(false);
        rootView.setClipEnabled(false);
        try {
            int src = AttrUtils.getIntValueByAttr(attrs, "iconSrc", SpeedDialActionItem.RESOURCE_NOT_SET);
            SpeedDialActionItem.Builder builder = new SpeedDialActionItem.Builder(getId(), src);
            String labelText = AttrUtils.getStringValueByAttr(attrs, "fabLabel", "");
            builder.setLabel(labelText);
            int fabBackgroundColor = UiUtils.getPrimaryColor(context);
            fabBackgroundColor = AttrUtils.getIntValueByAttr(attrs, "fabBackgroundColor", fabBackgroundColor);
            builder.setFabBackgroundColor(fabBackgroundColor);
            int labelColor = SpeedDialActionItem.RESOURCE_NOT_SET;
            labelColor = AttrUtils.getIntValueByAttr(attrs, "fabLabelColor", labelColor);
            builder.setLabelColor(labelColor);
            int labelBackgroundColor = SpeedDialActionItem.RESOURCE_NOT_SET;
            labelBackgroundColor = AttrUtils.getIntValueByAttr(attrs, "fabLabelBackgroundColor", labelBackgroundColor);
            builder.setLabelBackgroundColor(labelBackgroundColor);
            boolean labelClickable = AttrUtils.getBooleanValueByAttr(attrs, "fabLabelClickable", true);
            builder.setLabelClickable(labelClickable);
            setSpeedDialActionItem(builder.create());
        } catch (Exception e) {
            LogUtil.debug(TAG, "Failure setting FabWithLabelView icon");
        }
    }

    @Override
    public void setVisibility(int visibility) {
        super.setVisibility(visibility);
        getFab().setVisibility(visibility);
        if (isLabelEnabled()) {
            getLabelBackground().setVisibility(visibility);
        }
    }

    @Override
    public void setOrientation(int orientation) {
        super.setOrientation(orientation);
        setFabSize(mCurrentFabSize);
        if (orientation == VERTICAL) {
            setLabelEnabled(false);
        } else {
            setLabel(mLabelTextView.getText());
        }
    }

    /**
     * Return true if button has label, false otherwise.
     */
    public boolean isLabelEnabled() {
        return mIsLabelEnabled;
    }

    /**
     * Enables or disables label of button.
     */
    private void setLabelEnabled(boolean enabled) {
        mIsLabelEnabled = enabled;
        mLabelCardView.setVisibility(enabled ? Component.VISIBLE : Component.HIDE);
    }

    /**
     * Returns FAB labels background card.
     */
    public CardView getLabelBackground() {
        return mLabelCardView;
    }

    /**
     * Returns the {@link FloatingActionButton}.
     */
    public FloatingActionButton getFab() {
        return mFab;
    }

    public SpeedDialActionItem getSpeedDialActionItem() {
        if (mSpeedDialActionItem == null) {
            throw new IllegalStateException("SpeedDialActionItem not set yet!");
        }
        return mSpeedDialActionItem;
    }

    /**
     * Returns an instance of the {@link SpeedDialActionItem.Builder} initialized with the current instance of the
     * {@link SpeedDialActionItem} to make it easier to modify the current Action Item settings.
     */
    public SpeedDialActionItem.Builder getSpeedDialActionItemBuilder() {
        return new SpeedDialActionItem.Builder(getSpeedDialActionItem());
    }

    public void setSpeedDialActionItem(SpeedDialActionItem actionItem) {
        mSpeedDialActionItem = actionItem;
        if (actionItem.getFabType().equals(SpeedDialActionItem.TYPE_FILL)) {
            this.removeComponent(mFab);
            Component view = LayoutScatter.getInstance(getContext()).parse(ResourceTable.Layout_sd_fill_fab, this, true);
            FloatingActionButton newFab = (FloatingActionButton)view.findComponentById(ResourceTable.Id_sd_fab_fill);
            mFab = newFab;
        }
        setId(actionItem.getId());
        setLabel(actionItem.getLabel(getContext()));
        setFabContentDescription(actionItem.getContentDescription(getContext()));
        SpeedDialActionItem speedDialActionItem = getSpeedDialActionItem();
        setLabelClickable(speedDialActionItem != null && speedDialActionItem.isLabelClickable());
        setFabIcon(actionItem.getFabImageDrawable(getContext()));
        int imageTintColor = actionItem.getFabImageTintColor();
        if (imageTintColor == SpeedDialActionItem.RESOURCE_NOT_SET) {
            imageTintColor = UiUtils.getOnSecondaryColor(getContext());
        }
        boolean imageTint = actionItem.getFabImageTint();
        if (imageTint) {
            setFabImageTintColor(imageTintColor);
        }
        int fabBackgroundColor = actionItem.getFabBackgroundColor();
        if (fabBackgroundColor == SpeedDialActionItem.RESOURCE_NOT_SET) {
            fabBackgroundColor = UiUtils.getPrimaryColor(getContext());
        }
        setFabBackgroundColor(fabBackgroundColor);
        int labelColor = actionItem.getLabelColor();
        if (labelColor == SpeedDialActionItem.RESOURCE_NOT_SET) {
            labelColor = UiUtils.getColor(getContext(), ResourceTable.Color_sd_label_text_color);
        }
        setLabelColor(labelColor);
        int labelBackgroundColor = actionItem.getLabelBackgroundColor();
        if (labelBackgroundColor == SpeedDialActionItem.RESOURCE_NOT_SET) {
            labelBackgroundColor = UiUtils.getColor(getContext(), ResourceTable.Color_sd_label_background_color);
        }
        setLabelBackgroundColor(labelBackgroundColor);
        if (actionItem.getFabType().equals(SpeedDialActionItem.TYPE_FILL)) {
            getFab().setButtonSize(FloatingActionButton.SIZE_MINI);
        } else {
            getFab().setButtonSize(actionItem.getFabSize());
        }
        setFabSize(actionItem.getFabSize());
    }

    /**
     * Set a listener that will be notified when a menu fab is selected.
     *
     * @param listener listener to set.
     */
    public void setOnActionSelectedListener(SpeedDialView.OnActionSelectedListener listener) {
        mOnActionSelectedListener = listener;
        if (mOnActionSelectedListener != null) {
            setClickedListener(view -> {
                SpeedDialActionItem speedDialActionItem = getSpeedDialActionItem();
                if (mOnActionSelectedListener != null
                        && speedDialActionItem != null) {
                    if (speedDialActionItem.isLabelClickable()) {
                        //UiUtils.performTap(getLabelBackground());
                    } else {
                        //UiUtils.performTap(getFab());
                    }
                }
            });
            getFab().setClickedListener(view -> {
                SpeedDialActionItem speedDialActionItem = getSpeedDialActionItem();
                if (mOnActionSelectedListener != null
                        && speedDialActionItem != null) {
                    mOnActionSelectedListener.onActionSelected(speedDialActionItem);
                }
            });

            getLabelBackground().setClickedListener(view -> {
                SpeedDialActionItem speedDialActionItem = getSpeedDialActionItem();
                if (mOnActionSelectedListener != null
                        && speedDialActionItem != null
                        && speedDialActionItem.isLabelClickable()) {
                    mOnActionSelectedListener.onActionSelected(speedDialActionItem);
                }
            });
        } else {
            getFab().setClickedListener(null);
            getLabelBackground().setClickedListener(null);
        }

    }

    private void setFabSize(int fabSize) {
        try {
            int normalFabSizePx = (int) getResourceManager().getElement(ResourceTable.Float_sd_fab_normal_size).getFloat();
            int miniFabSizePx = (int) getResourceManager().getElement(ResourceTable.Float_sd_fab_mini_size).getFloat();
            int fabSideMarginPx = (int) getResourceManager().getElement(ResourceTable.Float_sd_fab_side_margin).getFloat();
            int fabSizePx = fabSize == FloatingActionButton.SIZE_NORMAL ? normalFabSizePx : miniFabSizePx;
            LayoutConfig rootLayoutParams;
            LayoutConfig fabLayoutParams = (LayoutConfig) mFab.getLayoutConfig();
            if (getOrientation() == HORIZONTAL) {
                rootLayoutParams = new LayoutConfig(ComponentContainer.LayoutConfig.MATCH_CONTENT, fabSizePx);
                rootLayoutParams.alignment = LayoutAlignment.END;

                if (fabSize == FloatingActionButton.SIZE_NORMAL) {
                    int excessMargin = (normalFabSizePx - miniFabSizePx) / 2;
                    fabLayoutParams.setMargins(fabSideMarginPx - excessMargin, 0, fabSideMarginPx - excessMargin, 0);
                } else {
                    fabLayoutParams.setMargins(fabSideMarginPx, 0, fabSideMarginPx, 0);
                }
            } else {
                rootLayoutParams = new LayoutConfig(fabSizePx, ComponentContainer.LayoutConfig.MATCH_CONTENT);
                rootLayoutParams.alignment = LayoutAlignment.VERTICAL_CENTER;
                fabLayoutParams.setMargins(0, 0, 0, 0);
            }

            setLayoutConfig(rootLayoutParams);
            mFab.setLayoutConfig(fabLayoutParams);
            mFab.updateFabMargin(getOrientation());
            mCurrentFabSize = fabSize;
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    /**
     * Sets fab drawable.
     *
     * @param mDrawable drawable to set.
     */
    private void setFabIcon(Element mDrawable) {
        mFab.setImageElement(mDrawable);
    }

    /**
     * Sets fab label․
     *
     * @param sequence label to set.
     */
    private void setLabel(CharSequence sequence) {
        if (!TextTool.isNullOrEmpty(sequence)) {
            mLabelTextView.setText(sequence.toString());
            setLabelEnabled(getOrientation() == HORIZONTAL);
        } else {
            setLabelEnabled(false);
        }
    }

    private void setLabelClickable(boolean clickable) {
        getLabelBackground().setClickable(clickable);
        getLabelBackground().setFocusable(clickable? FOCUS_ENABLE : FOCUS_DISABLE);
        getLabelBackground().setEnabled(clickable);
    }

    /**
     * Sets fab content description․
     *
     * @param sequence content description to set.
     */
    private void setFabContentDescription(CharSequence sequence) {
        if (!TextTool.isNullOrEmpty(sequence)) {
            mFab.setComponentDescription(sequence);
        }
    }

    /**
     * Sets fab image tint color in floating action menu.
     *
     * @param color color to set.
     */
    private void setFabImageTintColor(int color) {
        //ImageViewCompat.setImageTintList(mFab, ColorStateList.valueOf(color));
        // HarmonyOS暂时未找到对应实现方法，后续维护该功能
    }

    /**
     * Sets fab color in floating action menu.
     *
     * @param color color to set.
     */
    private void setFabBackgroundColor(int color) {
        mFab.setColorNormal(color);
    }

    private void setLabelColor(int color) {
        mLabelTextView.setTextColor(new Color(color));
    }

    private void setLabelBackgroundColor(int color) {
        if (color == Color.TRANSPARENT.getValue()) {
            ShapeElement normalBackground = new ShapeElement();
            normalBackground.setRgbColor(RgbColor.fromArgbInt(Color.TRANSPARENT.getValue()));

            mLabelCardView.setBackground(normalBackground);
            //mLabelCardViewElevation = mLabelCardView.getElevation();
//            mLabelCardView.setElevation(0);
        } else {
            ShapeElement normalBackground = new ShapeElement();
            normalBackground.setStroke(AttrHelper.fp2px(0.5f, mContext), new RgbColor(0xCCCCCC88));
            normalBackground.setRgbColor(RgbColor.fromArgbInt(color));
            normalBackground.setCornerRadius(AttrHelper.fp2px(4f, mContext));

            mLabelCardView.setBackground(normalBackground);

//            if (mLabelCardViewElevation != 0) {
//                mLabelCardView.setElevation(mLabelCardViewElevation);
//                mLabelCardViewElevation = 0;
//            }
        }
    }
}

